# -*- coding: utf-8 -*-
#coding = utf-8

from redis_operation import RedisOperation
from database_manager import DBManager
#from tcp_config import * as config
import tcp_config as config
import contrib
import logging
import datetime

DEVICE_STATUS = [0,1,2,3]
  # 0 
  # 1 exist in bind_devices
  # 2 not exist in bind_devices
  # 3 somewhere catch error
'''
MYSQLHOST = '192.168.1.101'
MYSQLUSER = 'admin'
MYSQLPWD = 'admin'
MYSQLDBNAME = 'et_go_db_test'
'''

'''
MYSQLHOST = 'etlinkingdb.mysql.rds.aliyuncs.com'#'192.168.1.101'
MYSQLUSER = 'et_dba'#'admin'
MYSQLPWD = '1tLiNk1nG_1tG0'#'admin'
MYSQLDBNAME = 'et_go_db_test'
'''

dbtool = DBManager(config.MYSQLHOST,config.MYSQLUSER,config.MYSQLPWD,config.MYSQLDBNAME)

class DataOperation:

	@staticmethod
	def get_gateway(ip):

		logger = logging.getLogger('et.kernel.tcp.DataOperation.get_gateway')
		return RedisOperation.set_gateway_by_ip(ip)

	@staticmethod
	def get_device(data, i): # i : 1, config data ; 2, sport data 

		logger = logging.getLogger('et.kernel.tcp.DataOperation.get_device')

		try:

			new_id = RedisOperation.get_deviceid()

			if i == 1:
				devce_data = data[21:27]

				RedisOperation.set_current_deviceid(contrib.get_string(devce_data))

				if devce_data == ['\xff','\xff','\xff','\xff','\xff','\xff']:

					if new_id == 'reset':

						return 'reset'

					DataOperation.__update_device_status(new_id,2)

					return new_id

				else:
					
					RedisOperation.set_all_deviceids(contrib.get_string(devce_data))

			elif i == 2:
				devce_data = data[0:6]
				if devce_data == ['\xff','\xff','\xff','\xff','\xff','\xff']:
					device = 'NoDevice'
					return device

			if new_id == 'reset':

				device = contrib.get_string(devce_data)

				DataOperation.__update_device_status(device,1)

				device = 'reset'
				return device

			device = contrib.get_string(devce_data)

			return device
		except Exception:
			logger.error(e)
			return None

	@staticmethod
	def __update_device_status(device, statusid):

		sql = "update deviceinfo set device_status = %(statusid)d, modifiedtime = now() where deviceid = '%(device)s' " % {'statusid':statusid, 'device':device}

		result = dbtool.operateDB('update',sql)

		return DataOperation.__reset_data()

	@staticmethod
	def update_device(devce_data, deviceid):
		logger = logging.getLogger('et.kernel.tcp.DataOperation.update_device')

		try:

			year = contrib.dec2hex(datetime.datetime.now().year-2000)
			month = contrib.dec2hex(datetime.datetime.now().month)
			day = contrib.dec2hex(datetime.datetime.now().day)
			hour = contrib.dec2hex(datetime.datetime.now().hour)
			minute = [chr(int('0x'+str(datetime.datetime.now().minute),16))]
			second = [chr(int('0x'+str(datetime.datetime.now().second),16))]

			time = year+month+day+hour+minute+second

			result = devce_data[0:6]+time+devce_data[12:21]

			return ''.join(result + contrib.string2hex(deviceid)[0:6])

		except Exception,e:
			logger.error(e)
			return ''.join(devce_data)

	@staticmethod
	def __reset_data():

		sql_pre = 'TRUNCATE TABLE '

		tables = ['pedometer_minute_data','sleep_minute_data','user_pedometer_daily_data','user_sleep_daily_data']

		for table in tables:
			sql = sql_pre + table

			result = dbtool.operateDB('update',sql)

			if not result:
				return False

		return True

	@staticmethod
	def __confirm_deviceid(deviceid):

		current_deviceid = RedisOperation.get_current_deviceid()

		if current_deviceid == deviceid:

			sql = "update deviceinfo set device_status = 3, modifiedtime = now() where device_status = 2 and deviceid = '%(deviceid)s' " % {'deviceid':deviceid}

			result = dbtool.operateDB('update',sql)

			return result
		else:
			return False


	@staticmethod
	def operate_daily_data(deviceid, data):

		logger = logging.getLogger('et.kernel.tcp.DataOperation.get_daily_data')

		try:

			userid = 0

			data = data[6:len(data)]
			sport_data = data[0:305]
			sleep_data = data[305:len(data)]

			DataOperation.__confirm_deviceid(deviceid)

			result_sport = DataOperation.get_sport_data(userid, deviceid, sport_data)
			if not result_sport:
				logger.debug('sport data op error')
				logger.debug(result_sport)

			result_sleep = DataOperation.get_sleep_data(userid, deviceid, sleep_data)
			return result_sleep
			
		except Exception, e:
			logger.error(e)
			return False

	@staticmethod
	def get_sport_data(userid, deviceid, byte_list):

		logger = logging.getLogger('et.kernel.tcp.DataOperation.get_sport_data')

		try:

			year = '20' + str(contrib.hex2dec(str(byte_list[0])))
			month = str(contrib.hex2dec(str(byte_list[1]))) if contrib.hex2dec(str(byte_list[1])) > 9 else '0' + str(contrib.hex2dec(str(byte_list[1])))
			day = str(contrib.hex2dec(str(byte_list[2]))) if contrib.hex2dec(str(byte_list[2])) > 9 else '0' + str(contrib.hex2dec(str(byte_list[2])))
			daykey = year + month + day
			#print daykey

			try:
				dt = datetime.datetime.strptime(daykey, '%Y%m%d')
			except Exception, e:
				logger.debug('daykey format is wrong')
				logger.error(e)
				#print e
				return False
			
			total_time = ord(byte_list[3])+256*ord(byte_list[4])
			total_step = ord(byte_list[8])*16777216+ord(byte_list[7])*65536+ord(byte_list[6])*256+ord(byte_list[5])
			total_calorie = ord(byte_list[12])*16777216+ord(byte_list[11])*65536+ord(byte_list[10])*256+ord(byte_list[9])
			total_mileage = ord(byte_list[16])*16777216+ord(byte_list[15])*65536+ord(byte_list[14])*256+ord(byte_list[13])
			detail_step = byte_list[17:305]

			weight = 75

			result_daily = DataOperation.set_sport_daily_data(userid, deviceid, daykey, total_time, total_step, total_mileage, total_calorie, weight)
			if not result_daily:
				#logger.debug('sport daily data op error')
				return False

			result_minute = DataOperation.set_sport_minute_data(userid, deviceid, daykey, detail_step, weight)
			return result_minute

		except Exception, e:
			logger.error(e)
			return False


	@staticmethod
	def get_sleep_data(userid, deviceid, data_list):

		logger = logging.getLogger('et.kernel.tcp.DataOperation.get_sleep_data')

		try:

			year = '20' + str(contrib.hex2dec(str(data_list[0]))) if contrib.hex2dec(str(data_list[0])) > 9 else '200' + str(contrib.hex2dec(str(data_list[0])))
			month = str(contrib.hex2dec(str(data_list[1]))) if contrib.hex2dec(str(data_list[1])) > 9 else '0' + str(contrib.hex2dec(str(data_list[1])))
			day = str(contrib.hex2dec(str(data_list[2]))) if contrib.hex2dec(str(data_list[2])) > 9 else '0' + str(contrib.hex2dec(str(data_list[2])))
			daykey = year + month + day
		
			sleep_start_hour = contrib.hex2dec(str(data_list[3]))
			sleep_start_minute = contrib.hex2dec_minute(contrib.hex2dec(str(data_list[4])))
			sleep_end_hour = contrib.hex2dec(str(data_list[5]))
			sleep_end_minute = contrib.hex2dec_minute(contrib.hex2dec(str(data_list[6])))

			try:

				dt_sleep_start = datetime.datetime.strptime(str(daykey)+' '+str(sleep_start_hour)+':'+str(sleep_start_minute), '%Y%m%d %H:%M')
				dt_sleep_end = datetime.datetime.strptime(str(daykey)+' '+str(sleep_end_hour)+':'+str(sleep_end_minute), '%Y%m%d %H:%M')

			except Exception, e:
				logger.debug('daykey format is wrong')
				logger.error(e)
				return False

			sleep_action = data_list[10:len(data_list)]


			result_daily = DataOperation.set_sleep_daily_data(userid, deviceid, daykey, sleep_start_hour, sleep_start_minute, sleep_end_hour, sleep_end_minute)

			if not result_daily:
				logger.debug('sleep daily data op error')
				return False

			result_minute = DataOperation.set_sleep_minute_data(userid, deviceid, daykey, sleep_start_hour, sleep_start_minute, sleep_action)
			return result_minute

		except Exception, e:
			logger.error(e)
			return None


	@staticmethod
	def __clean_data(userid, device, daykey, typeid, sleep_start_hour = 0):

		logger = logging.getLogger('et.kernel.tcp.DataOperation.clean_data')

		try:

			sql_condition = ' where uid = '+ str(userid) +' and daykey = ' + str(daykey) + ' and deviceid = \''+ str(device) +'\''

			if typeid == 1:
				table = 'user_pedometer_daily_data'
			elif typeid == 2:
				table = 'pedometer_minute_data'
			elif typeid == 3:
				table = 'user_sleep_daily_data'
				sql_condition = ' where uid = '+ str(userid) +' and daykey = ' + str(daykey) + ' and sleep_start_hour = ' + str(sleep_start_hour) + ' and deviceid = \''+ str(device) +'\''

			sql = 'TRUNCATE TABLE '+ table#'delete from '+ table + sql_condition

			result = dbtool.operateDB('update',sql)

			return result

		except Exception, e:
			logger.error(e)
			return False

	@staticmethod
	def __clean_sleep_data(userid, device, daykey, sleep_start_hour, sleep_start_minute):

		logger = logging.getLogger('et.kernel.tcp.DataOperation.clean_data')

		try:

			table = 'user_sleep_daily_data'
			sql_condition = ' where uid = '+ str(userid) +' and daykey = ' + str(daykey) + ' and sleep_start_hour = ' + str(sleep_start_hour) +' and sleep_start_minute = ' + str(sleep_start_minute) + ' and deviceid = \''+ str(device) +'\''

			sql = 'TRUNCATE TABLE '+ table#'delete from '+ table + sql_condition

			result = dbtool.operateDB('update',sql)

			return result

		except Exception, e:
			logger.error(e)
			return False

	@staticmethod
	def __clean_sleep_minute_data(userid, device, daykey, sleep_start_hour, sleep_start_minute):

		logger = logging.getLogger('et.kernel.tcp.DataOperation.clean_sleep_minute_data')

		try:

			sql_condition = ' where uid = '+ str(userid) +' and daykey = ' + str(daykey) + ' and hourkey = ' + str(sleep_start_hour) +' and minutekey = ' + str(sleep_start_minute) + ' and deviceid = \''+ str(device) +'\''

			sql = 'TRUNCATE TABLE sleep_minute_data'#'SELECT COUNT(dataid) AS cnt FROM sleep_minute_data' + sql_condition

			result = dbtool.operateDB('update',sql)

			return result

			#result = dbtool.operateDB('get',sql)

			#if int(result[0][0]) > 0:
				#return False
			#else:
				#return True 

		except Exception, e:
			logger.error(e)
			return False

	@staticmethod
	def set_sport_daily_data(userid, device, daykey, total_time, total_step, total_mileage, total_calorie, weight):

		logger = logging.getLogger('et.kernel.tcp.DataOperation.set_sport_daily_data')

		try:

			result_clean = DataOperation.__clean_data(userid, device, daykey, 1)
			if not result_clean:
				return False

			op_total_mileage = DataOperation.__get_mileage_by_step(total_step)
			op_total_calorie = DataOperation.__get_calorie_by_step(total_step,weight)

			sql = 'INSERT into user_pedometer_daily_data values(null,'+ str(userid) +',\''+str(device)+'\','+str(daykey)+','+str(total_time)+','+str(total_step)+','+str(op_total_mileage)+','+str(op_total_calorie)+',now(),now(),'+str(daykey)[0:6]+','+str(daykey)[0:4]+','+str(total_mileage)+','+str(total_calorie)+')'

			result = dbtool.operateDB('update',sql)

			return result

		except Exception, e:
			logger.error(e)
			return False

	@staticmethod
	def set_sleep_daily_data(userid, device, daykey, sleep_start_hour, sleep_start_minute, sleep_end_hour, sleep_end_minute):

		logger = logging.getLogger('et.kernel.tcp.DataOperation.set_sleep_daily_data')

		try:

			result_clean = DataOperation.__clean_sleep_data(userid, device, daykey, sleep_start_hour, sleep_start_minute)
			if not result_clean:
				return False

			sql = 'INSERT into user_sleep_daily_data values(null,'+str(userid)+',\''+str(device)+'\','+str(daykey)+','+str(sleep_start_hour)+','+str(sleep_start_minute)+','+str(sleep_end_hour)+','+str(sleep_end_minute)+',now(),now())'
			
			result = dbtool.operateDB('update',sql)

			return result

		except Exception, e:
			logger.error(e)
			return False


	@staticmethod
	def set_sport_minute_data(userid, device, daykey, minute_data, weight):

		logger = logging.getLogger('et.kernel.tcp.DataOperation.set_sport_minute_data')

		try:

			data_list = []
			final_list = []
			for i in range(0,len(minute_data),2):
				data_list.append(ord(minute_data[i+1])*256+ord(minute_data[i]))

			cnt = 0
			for i in data_list:
				if i >= 65535:
					cnt = cnt + 1

			if cnt == 144:
				return False

			result_clean = DataOperation.__clean_data(userid, device, daykey, 2)
			if not result_clean:
				return False

			hour = 0
			for i in range(0,len(minute_data)/2,6):
				for j in range(0,6):
					tmp_list = [userid, device, daykey, hour, j, data_list[i+j], DataOperation.__get_mileage_by_step(data_list[i+j]), DataOperation.__get_calorie_by_step(data_list[i+j],weight)]
					t = tuple(tmp_list)
					final_list.append(t)
				hour = hour + 1

			if len(final_list) != 144:
				return False

			sql = 'INSERT INTO pedometer_minute_data VALUES(null,%s,%s,%s,%s,%s,%s,%s,%s,NOW(),NOW())'
			result = dbtool.batch_insert(sql,final_list)

			if result == 144:
				return True
			else:
				return False

		except Exception, e:
			logger.error(e)
			return False

	@staticmethod
	def __get_mileage_by_step(step):
		mileage = step*60/100
		return mileage

	@staticmethod
	def __get_calorie_by_step(step,weight):
		calorie = step*int(weight)*54/10000
		return calorie

	@staticmethod
	def set_sleep_minute_data(userid, device, daykey, sleep_start_hour, sleep_start_minute, minute_data):

		logger = logging.getLogger('et.kernel.tcp.DataOperation.set_sleep_minute_data')

		final_list = []

		try:

			result_clean = DataOperation.__clean_sleep_minute_data(userid, device, daykey, sleep_start_hour, sleep_start_minute)
			if not result_clean:
				return False

			dt_str = str(daykey)+' '+str(sleep_start_hour)+':'+str(sleep_start_minute)
			dt = datetime.datetime.strptime(dt_str, '%Y%m%d %H:%M')

			sleep_timedelta = datetime.timedelta(0,600,0)

			for i in range(0,len(minute_data),4):

				if ord(minute_data[i]) == 255 and ord(minute_data[i+1]) == 255 and ord(minute_data[i+2]) == 255 and ord(minute_data[i+3]) == 255:
					break

				tmp_daykey = dt.strftime('%Y%m%d')
				tmp_list = [userid, device,daykey,tmp_daykey,dt.hour,dt.minute,ord(minute_data[i+3])*16777216+ord(minute_data[i+2])*65536+ord(minute_data[i+1])*256+ord(minute_data[i])]
				
				t = tuple(tmp_list)
				dt = dt + sleep_timedelta

				final_list.append(t)

			sql = 'INSERT INTO sleep_minute_data VALUES(null,%s,%s,%s,%s,%s,%s,%s,NOW(),NOW())'
			result = dbtool.batch_insert(sql,final_list)

			if result == len(final_list):
				return True
			else:
				return False

		except Exception, e:
			logger.error(e)
			return False



	'''
	@staticmethod
	def opeart_device_info(ip, device):

		logger = logging.getLogger('et.kernel.tcp.DataOperation.opeart_device_info')

		try:
			if RedisOperation.check_device_bind(device):
				device_detail = RedisOperation.get_device_info(device)
				if device_detail == {}:
					logger.debug('something error in redis')
					return None
				else:
					return device_detail

			else:
				result = RedisOperation.set_device_by_ip(ip, device)
				logger.debug(str(device)+' not bind')
				return None

		except Exception, e:
			logger.error(e)
			return None

	@staticmethod
	def update_device_time(devce_data):

		logger = logging.getLogger('et.kernel.tcp.DataOperation.update_device_time')

		try:

			year = contrib.dec2hex(datetime.datetime.now().year-2000)
			month = contrib.dec2hex(datetime.datetime.now().month)
			day = contrib.dec2hex(datetime.datetime.now().day)
			hour = contrib.dec2hex(datetime.datetime.now().hour)
			minute = [chr(int('0x'+str(datetime.datetime.now().minute),16))]
			second = [chr(int('0x'+str(datetime.datetime.now().second),16))]

			time = year+month+day+hour+minute+second

			result = devce_data[0:6]+time+devce_data[12:len(devce_data)]

			return ''.join(result)

		except Exception,e:
			logger.error(e)
			return ''.join(devce_data)

	@staticmethod
	def splice_device_info(devce_data, device_detail):

		logger = logging.getLogger('et.kernel.tcp.DataOperation.splice_device_info')

		try:

			height = contrib.dec2hex(device_detail['height'])
			weight = contrib.dec2hex(device_detail['weight'])
			age = contrib.dec2hex(device_detail['age'])

			device_info_list_1 = height+weight+age

			gender_data = contrib.hex2bin(devce_data[5])
			gender = device_detail['gender']
			gender_data[2] = gender

			gender_data = contrib.bin2hex(''.join(gender_data))

			year = contrib.dec2hex(datetime.datetime.now().year-2000)
			month = contrib.dec2hex(datetime.datetime.now().month)
			day = contrib.dec2hex(datetime.datetime.now().day)
			hour = contrib.dec2hex(datetime.datetime.now().hour)
			minute = [chr(int('0x'+str(datetime.datetime.now().minute),16))]
			second = [chr(int('0x'+str(datetime.datetime.now().second),16))]

			user_goal = contrib.dec2hex(device_detail['user_goal'],6)

			sleep_start = device_detail['sleep_start'].split(',')
			sleep_start_hour = contrib.dec2hex(sleep_start[0])
			sleep_start_minute = [chr(int('0x'+str(sleep_start[1]),16))]

			sleep_end = device_detail['sleep_end'].split(',')
			sleep_end_hour = contrib.dec2hex(sleep_end[0])
			sleep_end_minute = [chr(int('0x'+str(sleep_end[1]),16))]

			auto_time = device_detail['auto_time'].split(',')
			auto_time_hour = contrib.dec2hex(auto_time[0])
			auto_time_minute = [chr(int('0x'+str(auto_time[1]),16))]

			device_info_list_2_a = gender_data+year+month+day+hour+minute+second+user_goal
			device_info_list_2_b = sleep_start_hour+sleep_start_minute+sleep_end_hour+sleep_end_minute
			device_info_list_2_c = auto_time_hour+auto_time_minute

			device_info_list_2 = device_info_list_2_a + device_info_list_2_b + device_info_list_2_c

			result = devce_data[0:1]+device_info_list_1+devce_data[4:5]+device_info_list_2+devce_data[21:len(devce_data)]

			return ''.join(result)
		except Exception, e:
			logger.error(e)
			return ''.join(devce_data)

	'''